// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

#ifndef BMC_RECOVERY_H_
#define BMC_RECOVERY_H_

#include <stdbool.h>
#include "status/rot_status.h"
#include "host_irq_control.h"
#include "host_processor.h"
#include "crypto/hash.h"
#include "crypto/rsa.h"
#include "platform.h"
#include "host_control.h"


/*
 * Control settings for host rollback and recovery.
 */
struct bmc_recovery_control {
	int min_wdt;		/**< The minimum number of watchdog events to wait before starting recovery. */
	uint32_t msec;		/**< The number of milliseconds to use for the timeout clock. */
};

/**
 * API for handling BMC watchdog boot recovery.
 */
struct bmc_recovery {
	/**
	 * Update the recovery state machine for a BMC reset event.
	 *
	 * @param recovery The BMC recovery state machine to update.
	 */
	void (*on_host_reset) (struct bmc_recovery *recovery);

	/**
	 * Update the recovery state machine when the BMC comes out of reset.
	 *
	 * @param recovery The BMC recovery state machine to update.
	 */
	void (*on_host_out_of_reset) (struct bmc_recovery *recovery);

	/**
	 * Update the recovery state machine for a chip select 0 assertion event.
	 *
	 * @param recovery The BMC recovery state machine to update.
	 */
	void (*on_host_cs0) (struct bmc_recovery *recovery);

	/**
	 * Update the recovery state machine for a chip select 1 assertion event.
	 *
	 * @param recovery The BMC recovery state machine to update.
	 * @param hash The hash engine to use during flash validation.
	 * @param rsa The RSA engine to use for signature verification.
	 *
	 * @return 0 if recovery was successful or no recovery was performed.  Otherwise, the error
	 * status of the recovery operation.
	 */
	int (*on_host_cs1) (struct bmc_recovery *recovery, struct hash_engine *hash,
		struct rsa_engine *rsa);

	struct host_irq_control *irq;			/**< Control for enabling and disable host IRQs. */
	struct host_processor *host;			/**< The BMC host for recovery operations. */
	int state;								/**< The current state of the recovery manager. */
	platform_clock timeout;					/**< The timeout clock to use to control recovery triggers. */
	struct bmc_recovery_control rec_ctrl;	/**< Control settings for host recovery. */
	int num_wdt;							/**< A counter for the number of watchdog events. */
	bool skip_recovery;						/**< Don't execute recovery on future events. */
	struct host_control *control;			/**< The interface for hardware control of the host. */
};


/**
 * The states for the recovery manager.
 */
enum {
	BMC_RECOVERY_STATE_RUNNING = 0,		/**< The host is running normally. */
	BMC_RECOVERY_STATE_IN_RESET,		/**< The host is in reset. */
	BMC_RECOVERY_STATE_EXIT_RESET,		/**< The host has exited reset. */
	BMC_RECOVERY_STATE_ROLLBACK_DONE,	/**< The rollback to previous flash was successful. */
};


int bmc_recovery_init (struct bmc_recovery *recovery, struct host_irq_control *irq,
	struct host_processor *host, struct host_control *control,
	struct bmc_recovery_control *rec_ctrl);
void bmc_recovery_release (struct bmc_recovery *recovery);

int bmc_recovery_set_initial_state (struct bmc_recovery *recovery, bool in_reset);


#define	BMC_RECOVERY_ERROR(code)		ROT_ERROR (ROT_MODULE_BMC_RECOVERY, code)

/**
 * Error codes that can be generated by the BMC recovery state machine.
 *
 * Note: Commented error codes have been deprecated.
 */
enum {
	BMC_RECOVERY_INVALID_ARGUMENT = BMC_RECOVERY_ERROR (0x00),			/**< Input parameter is null or not valid. */
	BMC_RECOVERY_NO_MEMORY = BMC_RECOVERY_ERROR (0x01),					/**< Memory allocation failed. */
	BMC_RECOVERY_HOST_RESET_FAILED = BMC_RECOVERY_ERROR (0x02),			/**< Failure while processing host reset event. */
	BMC_RECOVERY_HOST_EXIT_RESET_FAILED = BMC_RECOVERY_ERROR (0x03),	/**< Failure while processing host reset exit event. */
	BMC_RECOVERY_CS0_FAILED = BMC_RECOVERY_ERROR (0x04),				/**< Failure while processing CS0 event. */
	BMC_RECOVERY_CS1_FAILED = BMC_RECOVERY_ERROR (0x05),				/**< Host firmware could not be recovered to a previous state. */
	// BMC_RECOVERY_INVALID_MIN_WDT = BMC_RECOVERY_ERROR (0x06),		/**< Invalid minimum watchdog event value. */

};


#endif /* BMC_RECOVERY_H_ */
